<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>概述</title>
</head>
<body>
  <div>
    <p>ES5的对象属性名都是字符串，这容易造成属性名的冲突。比如，你使用了一个他人提供的对象，但又想为这个对象
      添加新的方法(mixin模式)，新方法的名字就可能与现有方法产生冲突。如果有一个机制，保证每个属性的名字都是独一无二的就好了。
      这样就从根本上防止了属性名的冲突。这就是ES6引入Symbol的原因。

      ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型，
      前6种是：undefined, null, 布尔值(Boolean),字符串(String),数值(Number),对象(Object)

      Symbol值通过Symbol函数生成，这就是说，对象的属性名现在可以有俩种类型，一种是原来的字符串类型，另一种是新增的Symbol类型。
      凡事属性名属于Symbol类型，就都是独一无二的，可以保证不会与其他属性名产生冲突。
    </p>
    <script>
      // kk
      var s = Symbol();
      console.log(typeof s); // symbol
      // 注意： Symbol函数前不能使用new命令，否则会报错。这是因为生成的Symbol是一个原始类型的值，不是对象！
      // 也就是说，由于Symbol值不是对象，所以不能添加属性，基本上，它是一种类似于字符串的数据类型。
      // Symbol函数可以接受一个字符串作为参数，表示对Symbol实例的描述，主要是为了在控制台显示。或者转为字符串时，比较容易区分。
      var s1 = Symbol('foo');
      var s2 = Symbol('bar');
      console.log(s1)//Symbol(foo)
      console.log(s2)//Symbol(bar)
      /**
      上面代码中，s1和s2是俩个Symbol值，如果不加参数，它们在控制台输出都是Symbol(),不利于区分，
      有了参数以后，就能区分了。
      如果Symbol的参数是一个对象，就会调用该对象的toString方法，将其转为字符串。然后才会生成一个Symbol值。

      注意，Symbol函数的参数只是表示对当前 Symbol 值的描述，因此相同参数的Symbol函数的返回值是不相等的。

      Symbol值不能与其他类型的值进行运算，会报错。
      */
      var sym = Symbol('My symbol');
      // var b = 'a' + sym; // Cannot convert a Symbol value to a string
      // 但是，Symbol值可以显示转为字符串。
      var c = String(sym);
      console.log(c)// Symbol(My symbol)
      var d = sym.toString();
      console.log(d) // Symbol(My symbol)

      // Symbol值也可以转为布尔值，但是不能转为数值。
      var sym = Symbol();
      Boolean(sym) // true
      !sym; // false
      if (sym) {
        //...
      };
      // Number(sym);// 报错
    </script>
  </div>
</body>
</html>